/***************************************************************************\
 * The Mattise Kernel														*
 * Copyright 2007 Matthew Iselin											*
 * Licensed under the GPL													*
 *																			*
 * timer.cc																	*
 *																			*
 * Hardware timer utilities, and the control center of the kernel: the		*
 * timer interrupt handler.													*
 *																			*
\***************************************************************************/

#include <asm/io.h>
#include "debug.h"
#include "kernel.h"
#include "mt.h"
#include "it.h"

// sets the clock rate, in counts per second
void SetClockRate( int hz )
{
	int divisor = 1193180 / hz;   /* Calculate our divisor */
	outb(0x43, 0x36);             /* Set our command byte 0x36 */
	outb(0x40, divisor & 0xFF);   /* Set low byte of divisor */
	outb(0x40, divisor >> 8);     /* Set high byte of divisor */
}

// tick timers
volatile unsigned int tick = 0;
volatile unsigned int sc = 0;

// rate for the clock in ticks per second
const int clockrate = 1000;

// timer IRQ handler
void timer_handler(uint32_t line)
{
	// increment the tick timer
	tick++;

	// check for second
	if( tick % clockrate == 0 )
	{
		sc++;
	}

	// acknowledge PIC
	outb(0x20, 0x20);
	outb(0x20, 0xA0);
	
	// handle multitasking - task switch
	if( mtenabled() /*&& tick % 10 == 0*/ ) { resched(); };
}

// installs the timer
void install_timer()
{
	iroute_makehook(0x20, &timer_handler);
	// set the clock to tick every millisecond
	SetClockRate( clockrate );
}

// sleep/delay
void sleep( int seconds )
{
	// start time
	unsigned int now = sc;
	
	// wait...
	while( sc - now != seconds );
}
void delay( int ms )
{
	// start time
	unsigned int now = tick;
	
	// wait...
	while( tick - now != ms );
}

// clock count
unsigned int clock()
{
	return tick;
}
